import socket
import threading

import BaseConfig
from Components.MapReduce import MapReduce
from Components.ServerNodeManage import ServerNodeManage
from Exception import ConfigerError


class Oneesama:
    def __init__(self, *, Config: BaseConfig.BaseConfig):
        self.Config = Config
        self.startAccept = False
        self.SocketList = list()

        self.console = self.Config.GetConsoleLog()
        print(self.console.using_method)
        self.port = Config.GetPort()

    @property
    def sisters_count(self):
        return len(self.Config.sisters)

    def set_datas(self, data, map_it=None):
        """
        设置 datas 给Oneesama
        :param data: 数据 需要是迭代器
        :param map_it: 是否将他们分成一块一块的 默认是否
        :return:
        """
        if map_it is not None:
            self.data_iter = MapReduce.Map(data, self.send_2_all())
        else:
            self.data_iter = data

    def give_sisters(self, group="all"):
        """
        将设置好的数据交给子服务器
        :return:
        """

    def creat_server(self, timeout=None):
        self.console.using_method(f"【Oneesama】创建服务器 端口{self.port}")
        self.startAccept = True  # 开启服务器
        self.MasterSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.MasterSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 取消他的WIATTIME
        self.MasterSocket.bind(("", self.port))
        self.MasterSocket.listen(255)
        if timeout == None:
            func_accept = threading.Thread(target=ServerNodeManage.o_get_accept,
                                           args=(self, self.MasterSocket, self.console.using_method))
        else:
            func_accept = threading.Thread(target=ServerNodeManage.o_get_accept,
                                           args=(self, self.MasterSocket, self.console.using_method, timeout))
        func_accept.run()

    def send_2_all(self):
        """
        发送集群激活信息给配置好的服务器
        """

        for i in self.Config.sisters:
            ip = i.get("ip")
            name = i.get("name")
            port = i.get("port")
            group = i.get("group")

            name = name if name is not None else ip
            port = port if port is not None else 10032
            group = group if group is not None else "Any"

            if isinstance(ip, str) and isinstance(name, str):
                self.console.using_method(f"【Oneesama_链接中】提示 名称:{name} ip:{ip}的Sister 加入集群")
                socket_to_client = ServerNodeManage.connect((ip, port - 1))
                socket_to_client.close()
                # 这个不是我们使用的通信套接字 而是对子服务器链接的尝试与发送自己信息的套接字
                self.SocketList.append(
                    {"name": name, "ip": ip, "group": group}
                )

            else:
                raise ConfigerError("配置类的sister编辑错误")

    def __del__(self):
        for i in self.SocketList:
            i.get("socket").close() if isinstance(i.get('socket'), socket.socket) else ...
